package com.ea.eadp.nexus.test.pageDefinition;

import com.ea.eadp.test.shared.utility.RandomFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import com.ea.eadp.nexus.test.common.PageOperation;
import com.ea.eadp.nexus.test.common.SystemProperties;
import com.ea.eadp.nexus.test.common.TestUtil;

/**
 * Created with IntelliJ IDEA.
 * User: FMWang
 * Date: 7/3/13
 * Time: 2:39 PM
 * To change this template use File | Settings | File Templates.
 */
public class TwoFactorAuth_PC extends BasePage implements TwoFactorAuthClientWithCode<WebDriver> {
    // two factor cases only
    public static final String redirectURI = SystemProperties.instance().getProperty(SystemProperties.LockboxUri);
    private static Log log = LogFactory.getLog(TwoFactorAuth_PC.class);

    public TwoFactorAuth_PC(WebDriver driver) {
        super(driver, TwoFactorAuth_PC.class);
        timeout=15;
    }

    // code and backup code use the same textbox
    public void setTwoFactorCode(String twoFactorCode) {
        driver.switchTo().window(this.operationWindowHandle);
        log.info(twoFactorCode);
        this.waitForWebElementPresent(txtBox_twofactorCode);
        PageOperation.SendKeyToElement(driver, "twoFactorCode", twoFactorCode);
    }
    public void skipUpdateToAppAuth() {
        try {
            WebDriverWait wait = new WebDriverWait(driver, 5);
            wait.until(ExpectedConditions.visibilityOfElementLocated(btn_cancel));
            driver.findElement(btn_cancel).click();
        } catch (TimeoutException e) {
           log.warn(e.getMessage());
        }
    }
    public void clickContinue() {
        try {
            driver.findElement(btn_continue).click();

        }catch (NoSuchElementException e){
            log.warn(e.getMessage());
        }
    }
    public void skipSetName() {
        try {
            driver.findElement(skipSetName).click();

        }catch (NoSuchElementException e){
            log.warn(e.getMessage());
        }
    }
    public void clickSubmit() throws Exception {
        clickSubmitWithoutWait();
        skipUpdateToAppAuth();
        WebDriverWait wait = new WebDriverWait(driver, timeout);
        ExpectedCondition e = new ExpectedCondition<Boolean>() {
            @Override
            public Boolean apply(WebDriver d) {
                return (TestUtil.getCurrentUrl(d).contains(redirectURI));
            }
        };
        log.info(TestUtil.getCurrentUrl(driver));
        wait.until(e);
        log.info(TestUtil.getCurrentUrl(driver));
        if (!TestUtil.getCurrentUrl(driver).contains(redirectURI) && !TestUtil.getCurrentUrl(driver).contains("s2")) {
            throw new Exception("validate goes to redirect uri.");
        }
    }

    public void clickSubmitWithoutWait() throws Exception {
        driver.switchTo().window(this.operationWindowHandle);
        waitForWebElementPresent(btn_submit);
        driver.findElement(btn_submit).click();
    }

    public void clickCancel() throws Exception {
        driver.switchTo().window(this.operationWindowHandle);
        waitForWebElementPresent(btn_cancel);
        driver.findElement(btn_cancel).click();
    }

    public void clickResendCode() throws Exception {
        driver.switchTo().window(this.operationWindowHandle);
        waitForWebElementPresent(link_resendCode);
        driver.findElement(link_resendCode).click();
    }

    public void clickUseBackupCode() throws Exception {
        driver.switchTo().window(this.operationWindowHandle);
        waitForWebElementPresent(link_useBackupCode);
        driver.findElement(link_useBackupCode).click();
    }

    public boolean verifyCheckedTrustThisDeviceBox(){
        driver.switchTo().window(this.operationWindowHandle);
        waitForWebElementPresent(lbl_trustThisDevice);
        return driver.findElement(chkbox_trustThisDevice).isSelected();
    }
    public void checkTrustThisDeviceBox(boolean checked) throws Exception {
        driver.switchTo().window(this.operationWindowHandle);
        waitForWebElementPresent(lbl_trustThisDevice);
        if (checked != driver.findElement(chkbox_trustThisDevice).isSelected()) {
            driver.findElement(lbl_trustThisDevice).click();
        }
    }

    private By link_resendCode = By.id("resend_code_link");
    private By btn_submit = By.id("btnLogin");
    private By btn_cancel = By.id("btnCancel");
    private By link_useBackupCode = By.id("use_backup_code_link");
    private By chkbox_trustThisDevice = By.id("trustThisDevice");
    private By lbl_trustThisDevice = By.id("label-trustThisDevice");
    private By txtBox_twofactorCode = By.id("twoFactorCode");
    private By btn_continue=By.id("submit-btn");
    private By skipSetName=By.xpath("//*[@id='panel-profile-settings']/div[4]/a[1]/span/span");
    @Override
    public WebDriver getClient() {
        return driver;
    }

    @Override
    public void setClient(WebDriver client) {
        throw new UnsupportedOperationException(String.format("client in %s is immutable", getClass().getSimpleName()));
    }

    @Override
    public Status getStatus() throws Exception {
        try {
            driver.findElement(By.id("email"));
            driver.findElement(By.id("password"));
            return Status.REGULAR_AUTH;
        } catch (NoSuchElementException e) {
            // do nothing
        }

        try {
            driver.findElement(txtBox_twofactorCode);
            return Status.CHALLENGING_AUTH;
        } catch (NoSuchElementException e) {
            // do nothing
        }

        return Status.UNKNOWN;
    }

    @Override
    public void goAuthentication() throws Exception {
        Signin_PC signin_pc = new Signin_PC(driver);
        signin_pc.navigate();
        signin_pc.waitForWebElementPresent(By.id("email"));
    }

    @Override
    public void goAuthenticationForSpecific(String clientId) throws Exception {
        Signin_PC signin_pc = new Signin_PC(driver);
        signin_pc.navigate(TestUtil.BaseConnectURI() + TestUtil.getGenericConnectUri(clientId, "pc/login") + "&pc_machine_id=" + RandomFactory.getRandomStringOfAlphabetOrNumeric(40));
        signin_pc.waitForWebElementPresent(By.id("email"));
    }
    @Override
    public void goAuthenticationForSpecific(String clientId, String redirectUri) throws Exception {
        Signin_PC signin_pc = new Signin_PC(driver);
        signin_pc.navigate(TestUtil.BaseConnectURI() + TestUtil.getGenericConnectUri(clientId, "pc/login", redirectUri) + "&pc_machine_id=" + RandomFactory.getRandomStringOfAlphabetOrNumeric(40));
        signin_pc.waitForWebElementPresent(By.id("email"));
    }
    public void goAuthenticationForSpecific(String clientId, String redirectUri,String scopes) throws Exception {
        Signin_PC signin_pc = new Signin_PC(driver);
        signin_pc.navigate(TestUtil.BaseConnectURI() + TestUtil.getGenericConnectUri(clientId, "pc/login", redirectUri,scopes) + "&pc_machine_id=" + RandomFactory.getRandomStringOfAlphabetOrNumeric(40));
        signin_pc.waitForWebElementPresent(By.id("email"));
    }
    @Override
    public void login(String username, String password) throws Exception {
        Signin_PC signin_pc = new Signin_PC(driver);
        signin_pc.setSigninEmail(username);
        Thread.sleep(1000);
        signin_pc.setSigninPassword(password);
        signin_pc.clickToSigninCompleteWithSpecific(redirectURI);
    }

    @Override
    public void respondToChallenge(String answer) throws Exception {
        setTwoFactorCode(answer);
        clickSubmit();
    }

    @Override
    public String getInfoMessage() throws Exception {
        try {
            return driver.findElement(By.cssSelector("#pc-content-login .general-info-banner-tfa")).getText();
        } catch (NoSuchElementException e) {
            return null;
        }
    }

    @Override
    public String getErrorMessage() throws Exception {
        String message = null;

        // specific messages take priority over general message
        try {
            message = driver.findElement(By.id("resend-error-code")).getText();
        } catch (NoSuchElementException e) {
            // do nothing
        }

        try {
            message = driver.findElement(By.cssSelector("#pc-content-login .general-error")).getText();
        } catch (NoSuchElementException e) {
            // do nothing
        }

        return message;
    }

    @Override
    public void askResendCode() throws Exception {
        clickResendCode();
    }

    @Override
    public void close() throws Exception {
        if (null != driver)
            driver.quit();
    }
}
